from typing import List, Dict

from backend.app.common.log import log
from backend.app.schemas.device import DeviceInfoSchema
from backend.app.schemas.search import AISearchReq, MeterMatchSchema, AttributeMatchSchema, \
    MatchTpEnum
from backend.app.services.prompt_service import MatchMeterService, RadioMatchService, ChoiceMatchService
from backend.app.services.tender.search import TenderDeviceMatchScoreChain


class AISearchService:
    """向量搜索设备"""

    @staticmethod
    async def search(req: AISearchReq) -> DeviceInfoSchema:
        """搜索"""
        query = req.keyword
        # query = await summarize_text(req.keyword)
        # 按照相关性排序
        # chain = TenderDeviceMatchChain(shop_id=shop_id)
        # 按照向量距离评分排序
        chain = TenderDeviceMatchScoreChain(req.platform)
        lists = await chain.search_list(query)
        log.info(f"[AISearchService][search] query: {query}")
        return lists


class MatchDeviceAttribute:
    """匹配设备属性"""
    _tp_service = dict()

    def __init__(self):
        self._tp_service = {
            MatchTpEnum.radio.value: RadioMatchService(),
            MatchTpEnum.choice.value: ChoiceMatchService(),
        }

    @staticmethod
    def match_attributes(lists: List[AttributeMatchSchema]) -> str:
        """根据关键词匹配参数信息"""
        keyword_list = []
        for at in lists:
            keyword_list.append(at.keyword)
        return ", ".join(keyword_list)

    @staticmethod
    async def match_meter_by_keyword(meter: str, keywords: str) -> Dict:
        """
        从设备属性中匹配关键参数信息
        :param meter:
        :param keywords:
        :return: map[key]str 关键参数对应的属性信息
        """
        match_service = MatchMeterService()
        lists = await match_service.search(meter, keywords)
        res = dict()
        for at in lists:
            res[at.attribute] = at.value
        return res

    async def match_keyword(self, description: str, attribute_req: AttributeMatchSchema):
        """
        按照要求格式化关键参数信息
        :param description: 关键参数信息
        :param attribute_req: 关键参数格式要求
        :return:
        """
        match_tp = attribute_req.tp.value
        tp_service = self._tp_service.get(match_tp)
        if not tp_service:
            attribute_req.math_text = description
            return attribute_req
        option_str = ", ".join(attribute_req.options)
        result = await tp_service.search(description, option_str)
        if not result:
            return
        if type(result) == list:
            attribute_req.match_list = result
        else:
            attribute_req.math_text = result
        return attribute_req

    async def search(self, req: MeterMatchSchema):
        """设备属性匹配"""
        # 从设备属性中匹配关键参数列表
        math_keys = self.match_attributes(req.attributes)
        # 从属性中提取所有的关键参数信息
        meter_map = await self.match_meter_by_keyword(req.meter, math_keys)

        # 根据关键属性的匹配类型获取对应的结果
        for index, at in enumerate(req.attributes):
            key_description = meter_map.get(at.keyword)
            if not key_description:
                # 忽略空属性
                continue
            # 按照关键参数匹配
            req.attributes[index] = await self.match_keyword(key_description, at)

        return req
